package com.wr.recruit.service.service.impl;

import com.wr.recruit.service.dao.dbo.CompanyDbo;
import com.wr.recruit.service.dao.dbo.DepartmentDbo;
import com.wr.recruit.service.dao.dbo.UserDbo;
import com.wr.recruit.service.dao.dbo.UserDepartmentDbo;
import com.wr.recruit.service.dao.repo.DepartmentRepo;
import com.wr.recruit.service.dao.repo.UserDepartmentRepo;
import com.wr.recruit.service.dao.repo.UserRepo;
import com.wr.recruit.service.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class DepartmentServiceImpl implements DepartmentService {

    private UserRepo userRepo;
    private DepartmentRepo departmentRepo;
    private UserDepartmentRepo userDepartmentRepo;

    @Autowired
    public DepartmentServiceImpl(UserRepo userRepo,
                                 DepartmentRepo departmentRepo,
                                 UserDepartmentRepo userDepartmentRepo) {
        this.userRepo = userRepo;
        this.departmentRepo = departmentRepo;
        this.userDepartmentRepo = userDepartmentRepo;
    }

    @Override
    @Transactional
    public DepartmentDbo createDepartment(DepartmentDbo departmentDbo) {
        DepartmentDbo allByDepartmentCode = departmentRepo.findAllByDepartmentName(departmentDbo.getDepartmentName());
        if (Objects.isNull(allByDepartmentCode))
            return departmentRepo.save(departmentDbo);
        return null;
    }

    @Override
    @Transactional
    public DepartmentDbo updateDepartment(DepartmentDbo departmentDbo) {
        DepartmentDbo allByDepartmentCode = departmentRepo.findAllByDepartmentCode(departmentDbo.getDepartmentCode());
        if (!Objects.isNull(allByDepartmentCode))
            return departmentRepo.save(departmentDbo);
        return null;
    }

    @Override
    @Transactional
    public void deleteDepartment(String departmentCode) {
        DepartmentDbo allByDepartmentCode = departmentRepo.findAllByDepartmentCode(departmentCode);
        allByDepartmentCode.setRevoked(true);
        departmentRepo.save(allByDepartmentCode);
    }

    @Override
    @Transactional
    public Page<DepartmentDbo> getDepartmentList(String companyCode, String departmentName, Integer pageSize, Integer pageNum) {
        Specification<DepartmentDbo> specification = new Specification<DepartmentDbo>() {
            @Override
            public Predicate toPredicate(Root<DepartmentDbo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate p1 = cb.equal(root.get("isRevoked").as(Boolean.class),false);
                Predicate p2 = cb.like(root.get("departmentName").as(String.class), "%"+departmentName+"%");
                Predicate p3 = cb.equal(root.get("companyCode").as(String.class),companyCode);
                query.where(cb.and(p3,cb.and(p1,p2)));
                return query.getRestriction();
            }
        };
        return departmentRepo.findAll(specification,new PageRequest(pageNum - 1, pageSize));
    }

    @Override
    @Transactional
    public DepartmentDbo getDepartment(String departmentCode) {
        return departmentRepo.findAllByDepartmentCode(departmentCode);
    }

    @Override
    @Transactional
    public DepartmentDbo getDepartment(String departmentCode, String companyCode) {
        return departmentRepo.findAllByDepartmentNameAndAndCompanyCode(departmentCode, companyCode);
    }

    @Override
    @Transactional
    public Boolean updateUserDepartment(String departmentCode, String userName) {
        DepartmentDbo allByDepartmentCode = departmentRepo.findAllByDepartmentCode(departmentCode);
        if (Objects.isNull(allByDepartmentCode)){
            UserDbo allById = userRepo.findAllByUserName(userName);
            if (!Objects.isNull(allById)){
                UserDepartmentDbo userDepartmentDbo = new UserDepartmentDbo();
                userDepartmentDbo.setDepartmentId(allByDepartmentCode.getId());
                userDepartmentDbo.setUserId(allById.getId());
                userDepartmentRepo.save(userDepartmentDbo);
                return true;
            }
        }
        return false;
    }

    @Override
    public List<UserDbo> getUserDepartment(String companyCode, String departmentCode) {
        DepartmentDbo departmentDbo = departmentRepo.findAllByDepartmentNameAndAndCompanyCode(departmentCode, companyCode);
        if (!Objects.isNull(departmentDbo)){
            List<UserDepartmentDbo> allByDepartmentId = userDepartmentRepo.findAllByDepartmentId(departmentDbo.getId());
            List<Integer> collect = allByDepartmentId.stream().map(UserDepartmentDbo::getUserId).collect(Collectors.toList());
            List<UserDbo> allByIdIn = userRepo.findAllByIdIn(collect);
            return allByIdIn;
        }
        return null;
    }
}
